package jcolorlinez;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.Toolkit;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingConstants;

@SuppressWarnings("serial")
public class BoardFrame extends JFrame implements Grid.Observer {
	private ScorePanel recordPanel; //(HeaderLine Left)For the best score in history
	private ChessPanel.ShowOnly[] nextPanels; //(HeaderLine Center)New chess for next round
	private ScorePanel scorePanel; //(HeaderLine Right)For current score
	private ChessPanel[][] chessPanels; //All chess in the chess board
	
	public final Grid grid; //The only data model
	public BoardFrame(Grid grid) {
		this.grid = grid;
		if (!grid.load()) {
			grid.init();
		}
		
		this.setLayout(new GridLayout(grid.getRows()+1, grid.getColumns())); //one extra row for HeaderLine

		//First row for record, new chess and score
		this.addHeaderLine();
		
		//Following rows for chess board
		this.chessPanels = new ChessPanel[grid.getRows()][grid.getColumns()];
		for (int row = 0; row < grid.getRows(); row++) {
			for (int col = 0; col < grid.getColumns(); col++) {
				ChessPanel chess = new ChessPanel(this, row, col);
				chessPanels[row][col] = chess;
				this.add(chess);
			}
		}
		grid.addObserver(this);

		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		this.addWindowListener(new WindowAdapter() {
			public void windowClosing(WindowEvent e) {
				((BoardFrame)e.getComponent()).grid.save();
			}
		});
		Dimension size = new Dimension(grid.getColumns()*60, (grid.getRows()+1)*60);
		Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
		this.setMinimumSize(size);
		this.setLocation((screen.width - size.width)/2, (screen.height - size.height)/2);
		this.setTitle("Java Color Linez");
	}

	private void addHeaderLine() {
		int space_before = (grid.getColumns()-2-Grid.NEW_CHESS_PER_ROUND-2)/2;
		int space_after = grid.getColumns()-2-Grid.NEW_CHESS_PER_ROUND-2-space_before;
		if (space_before<0) {
			throw new IllegalArgumentException("Grid doesn't have enough columns to place all necessary components");
		}
		
		recordPanel = new ScorePanel(this, true);
		this.add(recordPanel);
		for (int i=0; i<space_before; i++) {
			this.add(new HeaderLabel());
		}
		this.add(new HeaderLabel("Next"));
		nextPanels = new ChessPanel.ShowOnly[Grid.NEW_CHESS_PER_ROUND];
		for (int i=0; i<Grid.NEW_CHESS_PER_ROUND; i++) {
			nextPanels[i] = new ChessPanel.ShowOnly(this, i);
			this.add(nextPanels[i]);
		}
		this.add(new HeaderLabel("Colors"));
		for (int i=0; i<space_after; i++) {
			this.add(new HeaderLabel());
		}
		scorePanel = new ScorePanel(this, false);
		this.add(scorePanel);
	}
	
	@Override
	public void update(int row, int col) {
		switch (row) {
		case Grid.ROW_FOR_NEW_CHESS:
			nextPanels[col].repaint();
			break;
		case Grid.ROW_FOR_RECORD:
			recordPanel.setScore(col);
			break;
		case Grid.ROW_FOR_SCORE:
			scorePanel.setScore(col);
			break;
		case Grid.ROW_FOR_GAMEOVER:
			JOptionPane.showMessageDialog(getParent(), "Game over!", "Java Color Linez", JOptionPane.WARNING_MESSAGE);
			grid.init();
			break;
		default:
			chessPanels[row][col].repaint();
			break;
		}
	}
	
	private static class ScorePanel extends JPanel {
		private JTextField textField = new JTextField();
		public ScorePanel(BoardFrame board, boolean isRecord) {
			textField.setHorizontalAlignment(JTextField.RIGHT);
			textField.setEditable(false);
			this.setLayout(new GridBagLayout());
			GridBagConstraints c = new GridBagConstraints();
			c.fill = GridBagConstraints.HORIZONTAL;
			c.weightx = 1.0;
			if (isRecord) {
				c.insets = new Insets(0, 10, 0, 0);
				setScore(board.grid.getRecord());
			} else {
				c.insets = new Insets(0, 0, 0, 10);
				setScore(board.grid.getScore());
			}
			this.add(textField, c);
			this.setBackground(Color.DARK_GRAY);
		}
		public void setScore(int score) {
			textField.setText("" + score);
		}
	}
	
	private static class HeaderLabel extends JLabel {
		public HeaderLabel() {
			this("");
		}
		public HeaderLabel(String text) {
			super(text, SwingConstants.CENTER);
			this.setBackground(Color.DARK_GRAY);
			this.setForeground(Color.LIGHT_GRAY);
			this.setOpaque(true);
		}
	}
}
